﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using Caliburn.Micro;
using JY.Label.PrintHelper;
using JY.Label.PrintHelper.CommuicationModel;
using JY.Label.Test.Models;
using Microsoft.Win32;

namespace JY.Label.Test.ViewModels
{
    /// <summary>
    /// 主页面ViewModel
    /// </summary>
    public class ShellViewModel : Screen
    {
        public ShellViewModel()
        {
            this.DicDatas = new ObservableCollection<DicData>() { new DicData("Param1", "参数1") };
            this.LabelDataModel = new LabelDataModel();
            this.IsLabelDataModel = true;

            //ZPL打印命令预览
            this.PrintDensities = new Dictionary<int, string>()
            {
                {6,"6 dpmm（152 dpi）"},
                {8,"8 dpmm（203 dpi）"},
                {12,"12 dpmm（300 dpi）"},
                {24,"24 dpmm（600 dpi）"},
            };
            this.PrintDensity = this.PrintDensities.First(x => x.Key == 8);

            this.LabelSizeUnits = new List<LabelSizeUnit>()
            {
                LabelSizeUnit.厘米,
                LabelSizeUnit.毫米,
                LabelSizeUnit.英寸
            };
            this.LabelSizeUnit = this.LabelSizeUnits.First();
            this.LabelWeight = 6;
            this.LabelHeight = 4;

            //打印测试
            this.ComPorts = this.GetComPorts();
            this.BaudRates = new List<int>() { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200 };
            this.Parities = new List<string>(Enum.GetNames(typeof(Parity)));
            this.DataBitses = new List<int>() { 8, 7, 6 };
            this.StopBitses = new List<string>(Enum.GetNames(typeof(StopBits)));
            this.StopBitses.Remove(StopBits.None.ToString());

            this.ComPort = this.ComPorts.FirstOrDefault();
            this.BaudRate = 9600;
            this.ParityStr = this.Parities.FirstOrDefault();
            this.DataBits = this.DataBitses.FirstOrDefault();
            this.StopBitsStr = this.StopBitses.FirstOrDefault();

            this.PrinterIp = "192.168.1.111";
            this.PrinterPort = 9100;

            this.LptPortName = "Lpt1";

            this.PrinterName = "ZDesigner ZT230-200dpi ZPL";

            this.LabelEncodings = new Dictionary<Encoding, string>();
            this.LabelEncodings.Add(Encoding.UTF8, nameof(Encoding.UTF8));
            if (Encoding.Default.BodyName.ToUpper() != "GB2312")
            {
                this.LabelEncodings.Add(Encoding.GetEncoding("GB2312"), "GB2312");
            }
            this.LabelEncodings.Add(Encoding.Default, Encoding.Default.BodyName.ToUpper());
            this.LabelEncodings.Add(Encoding.ASCII, nameof(Encoding.ASCII));
            this.LabelEncodings.Add(Encoding.Unicode, nameof(Encoding.Unicode));
            this.LabelEncodings.Add(Encoding.UTF7, nameof(Encoding.UTF7));
            this.LabelEncodings.Add(Encoding.UTF32, nameof(Encoding.UTF32));
            this.LabelEncodings.Add(Encoding.BigEndianUnicode, nameof(Encoding.BigEndianUnicode));

            this.SelectLabelEncoding = this.LabelEncodings.First();

            this.InitView();
        }
        #region # 属性
        #region IsBusy——bool IsBusy

        private bool _isBusy;

        public bool IsBusy
        {
            get { return this._isBusy; }
            set { this._isBusy = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 标签数据模型——LabelDataModel LabelDataModel

        private LabelDataModel _labelDataModel;

        /// <summary>
        /// 标签数据模型
        /// </summary>
        public LabelDataModel LabelDataModel
        {
            get { return this._labelDataModel;}
            set { this._labelDataModel = value;base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 标签数据字典——ObservableCollection<DicData> DicDatas

        private ObservableCollection<DicData> _dicDatas;
        /// <summary>
        /// 标签数据字典
        /// </summary>
        public ObservableCollection<DicData> DicDatas
        {
            get { return this._dicDatas; }
            set { this._dicDatas = value; base.NotifyOfPropertyChange(); }
        }

        #endregion 

        #region 是否标签数据模型——bool IsLabelDataModel
        private bool _isLabelDataModel;

        /// <summary>
        /// 是否标签数据模型
        /// </summary>
        public bool IsLabelDataModel
        {
            get { return this._isLabelDataModel; }
            set { this._isLabelDataModel = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 标签模板——string LabelTemplate

        private string _labelTemplate;
        /// <summary>
        /// 标签模板
        /// </summary>
        public string LabelTemplate
        {
            get { return this._labelTemplate; }
            set { this._labelTemplate = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 标签命令——string LabelCommand

        private string _labelCommand;
        /// <summary>
        /// 标签命令
        /// </summary>
        public string LabelCommand
        {
            get { return this._labelCommand; }
            set { this._labelCommand = value; base.NotifyOfPropertyChange(); }
        }
        #endregion


        //ZPL打印命令预览
        #region ZPL标签命令——string ZplLabelCommand
        private string _zplLabelCommand;
        /// <summary>
        /// ZPL标签命令
        /// </summary>
        public string ZplLabelCommand
        {
            get { return this._zplLabelCommand; }
            set { this._zplLabelCommand = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 打印密度——Dictionary<int,string> PrintDensity
        private Dictionary<int, string> _printDensities;
        /// <summary>
        /// 打印密度
        /// </summary>
        public Dictionary<int,string> PrintDensities
        {
            get { return this._printDensities; }
            set { this._printDensities = value; base.NotifyOfPropertyChange(); }
        }

        private KeyValuePair<int, string> _printDensity;
        public KeyValuePair<int, string> PrintDensity
        {
            get { return this._printDensity; }
            set { this._printDensity = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 标签高度——double LabelHeight
        private double _labelHeight;
        /// <summary>
        /// 标签高度
        /// </summary>
        public double LabelHeight
        {
            get { return this._labelHeight; }
            set { this._labelHeight = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 标签宽度——double LabelWeight
        private double _labelWeight;
        /// <summary>
        /// 标签宽度
        /// </summary>
        public double LabelWeight
        {
            get { return this._labelWeight; }
            set { this._labelWeight = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 标签大小单位——List<LabelSizeUnit> LabelSizeUnits
        private List<LabelSizeUnit> _labelSizeUnits;
        /// <summary>
        /// 标签大小单位
        /// </summary>
        public List<LabelSizeUnit> LabelSizeUnits
        {
            get { return this._labelSizeUnits; }
            set { this._labelSizeUnits = value; base.NotifyOfPropertyChange(); }
        }
        private LabelSizeUnit _labelSizeUnit;
        /// <summary>
        /// 标签大小单位
        /// </summary>
        public LabelSizeUnit LabelSizeUnit
        {
            get { return this._labelSizeUnit; }
            set { this._labelSizeUnit = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region ZPL标签图片——BitmapImage ZplLabelImage
        private BitmapImage _zplLabelImage;
        /// <summary>
        /// ZPL标签图片
        /// </summary>
        public BitmapImage ZplLabelImage
        {
            get { return this._zplLabelImage; }
            set { this._zplLabelImage = value; base.NotifyOfPropertyChange(); }
        }
        #endregion


        //打印测试
        #region 打印标签命令——string PrintLabelCommand
        private string _printLabelCommand;
        /// <summary>
        /// 打印标签命令
        /// </summary>
        public string PrintLabelCommand
        {
            get { return this._printLabelCommand; }
            set { this._printLabelCommand = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 打印机IP——string PrinterIp
        private string _printerIp;
        /// <summary>
        /// 打印机IP
        /// </summary>
        public string PrinterIp
        {
            get { return this._printerIp; }
            set { this._printerIp = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 打印机Port——int PrinterPort
        private int _printerPort;
        /// <summary>
        /// 打印机Port
        /// </summary>
        public int PrinterPort
        {
            get { return this._printerPort; }
            set { this._printerPort = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region # 串口设置相关
        #region 操作串口显示文字——string OperationComStr
        private string _operationComStr;
        /// <summary>
        /// 操作串口显示文字
        /// </summary>
        public string OperationComStr
        {
            get { return this._operationComStr; }
            set { this._operationComStr = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 串口列表——List<string> ComPorts
        private List<string> _comPorts;
        /// <summary>
        /// 串口列表
        /// </summary>
        public List<string> ComPorts
        {
            get { return this._comPorts; }
            set { this._comPorts = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 串口——string ComPort
        private string _comPort;
        /// <summary>
        /// 串口
        /// </summary>
        public string ComPort
        {
            get { return this._comPort; }
            set { this._comPort = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 波特率列表——List<int> BaudRates
        private List<int> _baudRates;
        /// <summary>
        /// 波特率列表
        /// </summary>
        public List<int> BaudRates
        {
            get { return this._baudRates; }
            set { this._baudRates = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 波特率——int BaudRate
        private int _baudRate;
        /// <summary>
        /// 波特率
        /// </summary>
        public int BaudRate
        {
            get { return this._baudRate; }
            set { this._baudRate = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 校验位列表——List<string> Parities
        private List<string> _parities;
        /// <summary>
        /// 校验位列表
        /// </summary>
        public List<string> Parities
        {
            get { return this._parities; }
            set { this._parities = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 校验位——string ParityStr
        private string _parityStr;
        /// <summary>
        /// 校验位
        /// </summary>
        public string ParityStr
        {
            get { return this._parityStr; }
            set { this._parityStr = value; base.NotifyOfPropertyChange(); }
        }
        /// <summary>
        /// 校验位
        /// </summary>
        public Parity Parity
        {
            get
            {
                return (Parity)Enum.Parse(typeof(Parity), this.ParityStr);
            }
        }
        #endregion

        #region 数据位列表——List<int> DataBitses
        private List<int> _dataBitses;
        /// <summary>
        /// 数据位列表
        /// </summary>
        public List<int> DataBitses
        {
            get { return this._dataBitses; }
            set { this._dataBitses = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 数据位——int DataBits
        private int _dataBits;
        /// <summary>
        /// 数据位
        /// </summary>
        public int DataBits
        {
            get { return this._dataBits; }
            set { this._dataBits = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 停止位列表——List<string> StopBitses
        private List<string> _stopBitses;
        /// <summary>
        /// 停止位列表
        /// </summary>
        public List<string> StopBitses
        {
            get { return this._stopBitses; }
            set { this._stopBitses = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 停止位——StopBits StopBits
        private string _stopBitsStr;
        /// <summary>
        /// 停止位
        /// </summary>
        public string StopBitsStr
        {
            get { return this._stopBitsStr; }
            set { this._stopBitsStr = value; base.NotifyOfPropertyChange(); }
        }
        /// <summary>
        /// 停止位
        /// </summary>
        public StopBits StopBits
        {
            get
            {
                return (StopBits)Enum.Parse(typeof(StopBits), this.StopBitsStr);
            }
        }
        #endregion
        #endregion

        //Lpt打印
        #region 打印机Lpt端口名称——string LptPortName
        private string _lptPortName;
        /// <summary>
        /// 打印机Lpt端口名称
        /// </summary>
        public string LptPortName
        {
            get { return this._lptPortName; }
            set { this._lptPortName = value; base.NotifyOfPropertyChange(); }
        }
        #endregion


        //USB打印
        #region 打印机名称——string PrinterName
        private string _printerName;
        /// <summary>
        /// 打印机名称
        /// </summary>
        public string PrinterName
        {
            get { return this._printerName; }
            set { this._printerName = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 标签编码列表——Dictionary<Encoding,string> LabelEncodings
        private Dictionary<Encoding, string> _labelEncodings;
        /// <summary>
        /// 标签编码列表
        /// </summary>
        public Dictionary<Encoding, string> LabelEncodings
        {
            get { return this._labelEncodings; }
            set { this._labelEncodings = value; base.NotifyOfPropertyChange(); }
        }
        #endregion

        #region 标签编码——Encoding LabelEncoding
        private KeyValuePair<Encoding, string> _selectLabelEncoding;
        /// <summary>
        /// 标签编码列表
        /// </summary>
        public KeyValuePair<Encoding, string> SelectLabelEncoding
        {
            get { return this._selectLabelEncoding; }
            set { this._selectLabelEncoding = value; base.NotifyOfPropertyChange(); }
        }
        /// <summary>
        /// 标签编码
        /// </summary>
        public Encoding LabelEncoding
        {
            get { return this.SelectLabelEncoding.Key; }
        }
        #endregion
        #endregion

        #region # Action方法

        #region # 转换命令——void ConvertCommand()
        /// <summary>
        /// 转换命令
        /// </summary>
        public void ConvertCommand()
        {
            if (this.IsLabelDataModel)
            {
                var convertResult = LabelCmdConverter.LabelDataConvert(this.LabelTemplate, new LabelData()
                {
                    Param1 = this.LabelDataModel.Param1,
                    Param2 = this.LabelDataModel.Param2,
                    Param3 = this.LabelDataModel.Param3,
                    Param4 = this.LabelDataModel.Param4,
                    Param5 = this.LabelDataModel.Param5,
                    Param6 = this.LabelDataModel.Param6,
                    Param7 = this.LabelDataModel.Param7,
                    Param8 = this.LabelDataModel.Param8,
                    Param9 = this.LabelDataModel.Param9,
                });
                this.LabelCommand = convertResult.Value;
            }
            else
            {
                var convertResult = LabelCmdConverter.LabelDataDicConvert(this.LabelTemplate, this.DicDatas.ToDictionary(x => x.Key, x => x.Value));
                this.LabelCommand = convertResult.Value;
            }

            this.ZplLabelCommand = this.LabelCommand;
            this.PrintLabelCommand = this.LabelCommand;
        }
        #endregion

        #region # 重新加载标签模板——void ReloadLabelTemplate()
        /// <summary>
        /// 重新加载标签模板
        /// </summary>
        public void ReloadLabelTemplate()
        {
            var labelTemplatePath = AppDomain.CurrentDomain.BaseDirectory + @"LabelTemplates\LabelTemplate.txt";
            using (var sr = new StreamReader(labelTemplatePath, Encoding.UTF8))
            {
                this.LabelTemplate = sr.ReadToEnd();
                sr.Close();
            }
            //"注意这里LabelTemplate.txt文件编码方式为UTF8，如果标签模板乱码请修改代码编码格式！"
        }

        #endregion

        #region # 添加字典数据——void AddDicData()
        /// <summary>
        /// 添加字典数据
        /// </summary>
        public void AddDicData()
        {
            this.DicDatas.Add(new DicData($"Param{this.DicDatas.Count + 1}", "参数值"));
        }
        #endregion

        #region # 预览标签——void PreviewLabel()
        /// <summary>
        /// 预览标签
        /// </summary>
        public async void PreviewLabel()
        {
            #region 验证
            if (string.IsNullOrEmpty(this.ZplLabelCommand))
            {
                MessageBox.Show("ZPL标签命令为空！");
                return;
            } 
            #endregion

            #region 标签大小转换
            double weight = this.LabelWeight;
            double height = this.LabelHeight;
            if (this.LabelSizeUnit == LabelSizeUnit.厘米)
            {
                double coefficient = 0.3937008;
                weight = this.LabelWeight * coefficient;
                height = this.LabelHeight * coefficient;
            }
            else if (this.LabelSizeUnit == LabelSizeUnit.毫米)
            {
                double coefficient = 0.03937008;
                weight = this.LabelWeight * coefficient;
                height = this.LabelHeight * coefficient;
            }
            #endregion
            try
            {
                Application.Current.Dispatcher.BeginInvoke((System.Action)delegate ()
                {
                    this.ZplLabelImage = LabelaryApiService.GenerateLabelImage(this.ZplLabelCommand, this.PrintDensity.Key, weight, height);
                });
            }
            catch (Exception ex)
            {
                MessageBox.Show($"预览标签失败！{ex.Message}");
            }
        }
        #endregion

        #region # 串口打印标签——void PrintLabelByCom()
        /// <summary>
        /// 串口打印标签
        /// </summary>
        public async void PrintLabelByCom()
        {
            try
            {
                this.IsBusy = true;
                await Task.Run(() =>
                {
                    var comModel = new ComModel(this.LabelEncoding, this.ComPort, this.BaudRate, this.Parity, this.DataBits, this.StopBits);
                    LabelPrintHelper.PrintLabelByCom(this.PrintLabelCommand, comModel);
                });
                MessageBox.Show("打印成功！");
            }
            catch (Exception ex)
            {
                MessageBox.Show($"打印失败！{ex.Message}");
            }
            this.IsBusy = false;
        }
        #endregion

        #region # Tcp打印标签——void PrintLabelByTcp()
        /// <summary>
        /// Tcp打印标签
        /// </summary>
        public async void PrintLabelByTcp()
        {
            try
            {
                this.IsBusy = true;
                await Task.Run(() =>
                {
                    var tcpModel = new TcpModel(this.LabelEncoding, this.PrinterIp, this.PrinterPort);
                    LabelPrintHelper.PrintLabelByTcp(this.PrintLabelCommand, tcpModel);
                });
                MessageBox.Show("打印成功！");
            }
            catch (Exception ex)
            {
                MessageBox.Show($"打印失败！{ex.Message}");
            }
            this.IsBusy = false;
        }
        #endregion

        #region # Lpt打印标签——void PrintLabelByLpt()
        /// <summary>
        /// Lpt打印标签
        /// </summary>
        public async void PrintLabelByLpt()
        {
            try
            {
                this.IsBusy = true;
                await Task.Run(() =>
                {
                    var lptModel = new LptModel(this.LabelEncoding, this.LptPortName);
                    LabelPrintHelper.PrintLabelByLpt(this.PrintLabelCommand, lptModel);
                });
                
                MessageBox.Show("打印成功！");
            }
            catch (Exception ex)
            {
                MessageBox.Show($"打印失败！{ex.Message}");
            }
            this.IsBusy = false;
        }
        #endregion

        #region # USB打印标签——void PrintLabelByUsb()
        /// <summary>
        /// USB打印标签
        /// </summary>
        public async void PrintLabelByUsb()
        {
            try
            {
                this.IsBusy = true;
                await Task.Run(() =>
                {
                    var usbModel = new UsbModel(this.LabelEncoding, this.PrinterName);
                    LabelPrintHelper.PrintLabelByUsb(this.PrintLabelCommand, usbModel);
                });

                MessageBox.Show("打印成功！");
            }
            catch (Exception ex)
            {
                MessageBox.Show($"打印失败！{ex.Message}");
            }
            this.IsBusy = false;
        }
        #endregion
        #endregion

        #region # 方法

        #region # 初始化页面——void InitView()
        /// <summary>
        /// 初始化页面
        /// </summary>
        public void InitView()
        {
            this.ReloadLabelTemplate();
        }

        #endregion

        #region 从注册表获取系统串口列表——GetComPorts()
        /// <summary> 
        /// 从注册表获取系统串口列表 
        /// </summary> 
        private List<string> GetComPorts()
        {
            RegistryKey keyCom = Registry.LocalMachine.OpenSubKey("Hardware\\DeviceMap\\SerialComm");

            List<string> comPorts = new List<string>();
            if (keyCom != null)
            {
                string[] sSubKeys = keyCom.GetValueNames();
                foreach (string sName in sSubKeys)
                {
                    string sValue = (string)keyCom.GetValue(sName);
                    comPorts.Add(sValue);
                }
            }

            return comPorts;
        }
        #endregion
        #endregion
    }
}
